import { spawn } from 'child_process';
import path from 'path';
import fs from 'fs';
import config from './config';

export interface SDWebUIStatus {
  isRunning: boolean;
  startTime: Date | null;
  uptime: number;
  pid: number | null;
  sdWebUIPath: string;
  pythonPath: string;
  launchScript: string;
  logCount: number;
}

export class SDWebUILauncher {
  private static instance: SDWebUILauncher;
  private sdWebUIPath: string;
  private pythonPath: string;
  private launchScript: string;
  private process: any;
  private isRunning: boolean;
  private startTime: Date | null;
  private logs: string[];

  private constructor() {
    this.sdWebUIPath = config.sdWebUIPath;
    this.pythonPath = path.join(this.sdWebUIPath, 'python', 'python.exe');
    this.launchScript = path.join(this.sdWebUIPath, 'launch.py');
    this.process = null;
    this.isRunning = false;
    this.startTime = null;
    this.logs = [];
    
    // 添加初始化日志
    this.addLog('SD WebUI启动器已初始化');
    this.addLog(`SD WebUI路径: ${this.sdWebUIPath}`);
    this.addLog(`Python路径: ${this.pythonPath}`);
    this.addLog(`启动脚本: ${this.launchScript}`);
  }

  public static getInstance(): SDWebUILauncher {
    if (!SDWebUILauncher.instance) {
      SDWebUILauncher.instance = new SDWebUILauncher();
    }
    return SDWebUILauncher.instance;
  }

  public async startSDWebUI(): Promise<any> {
    this.addLog(`启动请求 - 当前状态: isRunning=${this.isRunning}, process=${this.process ? '存在' : 'null'}`);
    
    if (!this.checkPaths()) {
      throw new Error('SD WebUI路径不存在或无效');
    }

    if (this.isRunning) {
      this.addLog('SD WebUI已经在运行中');
      return {
        success: false,
        message: 'SD WebUI已经在运行中',
        status: this.getStatus()
      };
    }

    return new Promise((resolve, reject) => {
      this.logs = [];
      this.addLog('开始启动SD WebUI...');
      this.addLog(`Python路径: ${this.pythonPath}`);
      this.addLog(`启动脚本: ${this.launchScript}`);
      this.addLog(`工作目录: ${this.sdWebUIPath}`);

      try {
        // 设置 Git 环境变量
        this.addLog('设置Git环境变量...');
        const gitEnvSet = spawn('powershell', ['-Command', "$env:GIT_PYTHON_GIT_EXECUTABLE = 'E:\\aigc-edu\\sd-webui-aki-v4.11.1-cu128\\git\\cmd\\git.exe'; echo 'Git环境变量已设置: ' + $env:GIT_PYTHON_GIT_EXECUTABLE"], {
          cwd: this.sdWebUIPath,
          stdio: ['pipe', 'pipe', 'pipe']
        });

        gitEnvSet.stdout.on('data', (data: Buffer) => {
          const output = data.toString().trim();
          this.addLog(`[Git环境变量设置] ${output}`);
        });

        gitEnvSet.stderr.on('data', (data: Buffer) => {
          const output = data.toString().trim();
          this.addLog(`[Git环境变量设置错误] ${output}`);
        });

        gitEnvSet.on('close', (code: number) => {
          this.addLog(`Git环境变量设置完成，退出码: ${code}`);
          
          // 执行主启动命令
          this.process = spawn(this.pythonPath, [
            this.launchScript,
            '--medvram-sdxl',
            '--theme', 'dark',
            '--xformers',
            '--xformers-flash-attention',
            '--api',
            '--autolaunch',
            '--skip-python-version-check',
            '--skip-torch-cuda-test',
            '--skip-prepare-environment',
            '--do-not-download-clip',
            '--skip-version-check',
            '--update-check',
            '--no-download-sd-model'
          ], {
            cwd: this.sdWebUIPath,
            stdio: ['pipe', 'pipe', 'pipe'],
            env: {
              ...process.env,
              GIT_PYTHON_GIT_EXECUTABLE: 'E:\\aigc-edu\\sd-webui-aki-v4.11.1-cu128\\git\\cmd\\git.exe'
            }
          });

          this.isRunning = true;
          this.startTime = new Date();
          
          this.addLog(`进程已创建，PID: ${this.process.pid}`);

          this.process.stdout.on('data', (data: Buffer) => {
            const output = data.toString();
            this.addLog(`[STDOUT] ${output.trim()}`);
            
            if (output.includes('Running on local URL') || output.includes('http://127.0.0.1')) {
              this.addLog('SD WebUI启动成功！');
            }
          });

          this.process.stderr.on('data', (data: Buffer) => {
            const output = data.toString();
            this.addLog(`[STDERR] ${output.trim()}`);
          });

          this.process.on('close', (code: number) => {
            this.isRunning = false;
            this.process = null;
            this.addLog(`SD WebUI进程已退出，退出码: ${code}`);
          });

          this.process.on('error', (error: Error) => {
            this.isRunning = false;
            this.process = null;
            this.addLog(`启动错误: ${error.message}`);
            reject(error);
          });

          setTimeout(() => {
            this.addLog(`启动超时检查 - 当前状态: isRunning=${this.isRunning}, pid=${this.process?.pid || 'null'}`);
            resolve({
              success: true,
              message: 'SD WebUI启动命令已执行',
              status: this.getStatus(),
              pid: this.process ? this.process.pid : null
            });
          }, config.startTimeout);
        });

        gitEnvSet.on('error', (error: Error) => {
          this.addLog(`Git环境变量设置失败: ${error.message}`);
          // 即使设置失败也继续执行主启动命令
          this.process = spawn(this.pythonPath, [
            this.launchScript,
            '--medvram-sdxl',
            '--theme', 'dark',
            '--xformers',
            '--xformers-flash-attention',
            '--api',
            '--autolaunch',
            '--skip-python-version-check',
            '--skip-torch-cuda-test',
            '--skip-prepare-environment',
            '--do-not-download-clip',
            '--skip-version-check',
            '--update-check',
            '--no-download-sd-model'
          ], {
            cwd: this.sdWebUIPath,
            stdio: ['pipe', 'pipe', 'pipe'],
            env: {
              ...process.env,
              GIT_PYTHON_GIT_EXECUTABLE: 'E:\\aigc-edu\\sd-webui-aki-v4.11.1-cu128\\git\\cmd\\git.exe'
            }
          });

          this.setupMainProcessHandlers(resolve, reject);
        });


      } catch (error: any) {
        this.addLog(`启动异常: ${error.message}`);
        this.isRunning = false;
        this.process = null;
        reject(error);
      }
    });
  }

  public async stopSDWebUI(force: boolean = false): Promise<any> {
    this.addLog(`停止请求 - 当前状态: isRunning=${this.isRunning}, process=${this.process ? '存在' : 'null'}, pid=${this.process?.pid || 'null'}`);
    
    if (!this.isRunning && !force) {
      this.addLog('SD WebUI未在运行状态');
      return {
        success: false,
        message: 'SD WebUI未在运行'
      };
    }

    if (force && !this.isRunning) {
      this.addLog('强制停止：重置所有状态');
      this.isRunning = false;
      this.process = null;
      this.startTime = null;
      return {
        success: true,
        message: '状态已强制重置',
        status: this.getStatus()
      };
    }

    if (!this.process) {
      this.addLog('进程对象不存在，强制重置状态');
      this.isRunning = false;
      this.startTime = null;
      return {
        success: true,
        message: 'SD WebUI状态已重置',
        status: this.getStatus()
      };
    }

    return new Promise((resolve) => {
      this.addLog(`正在停止SD WebUI，进程ID: ${this.process.pid}`);
      
      try {
        const killProcess = spawn('taskkill', ['/F', '/T', '/PID', this.process.pid.toString()]);
        
        killProcess.on('close', (code: number) => {
          this.isRunning = false;
          this.process = null;
          this.startTime = null;
          this.addLog(`SD WebUI已停止，退出码: ${code}`);
          resolve({
            success: true,
            message: 'SD WebUI已停止',
            status: this.getStatus()
          });
        });

        killProcess.on('error', (error: Error) => {
          this.addLog(`停止错误: ${error.message}`);
          // 即使taskkill失败，也重置状态
          this.isRunning = false;
          this.process = null;
          this.startTime = null;
          resolve({
            success: false,
            message: `停止失败: ${error.message}`,
            status: this.getStatus()
          });
        });
      } catch (error: any) {
        this.addLog(`停止异常: ${error.message}`);
        // 异常情况下也重置状态
        this.isRunning = false;
        this.process = null;
        this.startTime = null;
        resolve({
          success: false,
          message: `停止异常: ${error.message}`,
          status: this.getStatus()
        });
      }
    });
  }

  public getStatus(): SDWebUIStatus {
    return {
      isRunning: this.isRunning,
      startTime: this.startTime,
      uptime: this.startTime ? Date.now() - this.startTime.getTime() : 0,
      pid: this.process ? this.process.pid : null,
      sdWebUIPath: this.sdWebUIPath,
      pythonPath: this.pythonPath,
      launchScript: this.launchScript,
      logCount: this.logs.length
    };
  }

  public getLogs(): string[] {
    return this.logs;
  }

  private addLog(message: string): void {
    const timestamp = new Date().toISOString();
    const logEntry = `[${timestamp}] ${message}`;
    this.logs.push(logEntry);
    
    if (this.logs.length > config.maxLogs) {
      this.logs = this.logs.slice(-config.maxLogs / 2);
    }
    
    console.log(logEntry);
  }

  private setupMainProcessHandlers(resolve: any, reject: any): void {
    this.isRunning = true;
    this.startTime = new Date();
    
    this.addLog(`进程已创建，PID: ${this.process.pid}`);

    this.process.stdout.on('data', (data: Buffer) => {
      const output = data.toString();
      this.addLog(`[STDOUT] ${output.trim()}`);
      
      if (output.includes('Running on local URL') || output.includes('http://127.0.0.1')) {
        this.addLog('SD WebUI启动成功！');
      }
    });

    this.process.stderr.on('data', (data: Buffer) => {
      const output = data.toString();
      this.addLog(`[STDERR] ${output.trim()}`);
    });

    this.process.on('close', (code: number) => {
      this.isRunning = false;
      this.process = null;
      this.addLog(`SD WebUI进程已退出，退出码: ${code}`);
    });

    this.process.on('error', (error: Error) => {
      this.isRunning = false;
      this.process = null;
      this.addLog(`启动错误: ${error.message}`);
      reject(error);
    });

    setTimeout(() => {
      this.addLog(`启动超时检查 - 当前状态: isRunning=${this.isRunning}, pid=${this.process?.pid || 'null'}`);
      resolve({
        success: true,
        message: 'SD WebUI启动命令已执行',
        status: this.getStatus(),
        pid: this.process ? this.process.pid : null
      });
    }, config.startTimeout);
  }

  private checkPaths(): boolean {
    try {
      const sdWebUIExists = fs.existsSync(this.sdWebUIPath);
      const pythonExists = fs.existsSync(this.pythonPath);
      const launchScriptExists = fs.existsSync(this.launchScript);

      this.addLog(`检查路径: SD WebUI=${sdWebUIExists}, Python=${pythonExists}, Launch Script=${launchScriptExists}`);

      return sdWebUIExists && pythonExists && launchScriptExists;
    } catch (error: any) {
      this.addLog(`路径检查错误: ${error.message}`);
      return false;
    }
  }
}
